home *** CD-ROM | disk | FTP | other *** search
/ The X-Philes (2nd Revision) / The X-Philes Number 1 (1995).iso / xphiles / hp48hor1 / dots.doc < prev    next >
Text File  |  1995-03-31  |  18KB  |  402 lines

  1. (Comp.sys.handhelds) 
  2. Item: 3834 by catto at author.ecn.purdue.edu 
  3. Author: [Erin S Catto] 
  4.   Subj: Fuzz & ML Blurbs 
  5.   Date: Tue Aug 13 1991 
  6.  
  7. Well I promised myself that I would pass on what I've learned once I figured 
  8. out what's going on with this machine language business.  Sorry, it's not a 
  9. game.  Anyway, here's a small program which simply draws random dots on the 
  10. stack display and exits when you press the drop key. 
  11.  
  12. I thank Jan Brittenson for the STAR assembler (excellent) and the MLDL (way 
  13. excellent). 
  14.  
  15. This program covers most of the key hardware questions a freshie might have. 
  16.  
  17. +  Drawing on the stack display at a coordinate (0-127,0-63) 
  18. +  Data storage acquisition so that data tables are temporary 
  19. +  Turning off keyboard interupts (go ahead, press ON-A-F, nothing happens) 
  20. +  Machine code keyboard scanning 
  21. +  How to get random numbers you can't depend on 
  22.  
  23.  
  24. I'll briefly cover a few topics: 
  25.  
  26.  
  27. Preserving the RPL Operating System 
  28. =================================== 
  29.  
  30. The HP48 has an operating system just like any other computer.  It was written 
  31. in System RPL and machine code.  The HP48 OS uses the registers d0, d1, b, and 
  32. d to take care of business, such as memory management and RPL command pointing. 
  33. Thus you must save these important register and restore them at the termination 
  34. of your machine code program.  You must also set the OS back on track.  Here's 
  35. how it's done: 
  36.  
  37. save_regs = #0679B      ;ml routines to handle these tasks 
  38. rest_regs = #067D2 
  39.  
  40. begin 
  41.                   call.a     save_regs      ;save registers 
  42.                            . 
  43.                            . 
  44.                            . 
  45.                   call.a     rest_regs      ;restore registers 
  46.                   move.a     @d0, a         ;a = next RPL instruction 
  47.                   add.a      5, d0          ;point d0 to following instruction 
  48.                   jump       @a             ;jump to instruction in a 
  49.                                             ;address of object prolog? 
  50. end 
  51.  
  52. Here's how I believe the last three instructions work: 
  53.  
  54.                                   d0 
  55.                                    | 
  56.                                    v 
  57. RPL instruction stream:  ... 11EC7|65547|EF9D7|83188|... 
  58.  
  59.       move.a    @d0, a       ;a gets 74556 
  60.       add.a     5, d0        ;does the following 
  61.  
  62.                                         d0 
  63.                                          | 
  64.                                          v 
  65. RPL instruction stream:  ... 11EC7|65547|EF9D7|83188|... 
  66.  
  67. Lets say at the address 74556 there is the RPL program prolog 02D9D then 
  68.  
  69.        jump     @a 
  70.  
  71. will jump to the address 02D9D, a chain of pointers. 
  72.  
  73. Now the operating system is back on track, refreshing the screen, handling the 
  74. keyboard, etc.  Evidence of this is seen when you exit the attached program, 
  75. the RPL OS automatically returns the screen to its normal state. 
  76.  
  77.  
  78. Drawing on the Stack Display 
  79. ============================ 
  80. The stack display contains two grobs: the stack-message grob and the menu grob. 
  81.  
  82. Statistics: 
  83.  
  84. + Screen Grob:   location of grob contained at #7055B 
  85.                  size = 56 rows high by 136 bits wide (34 nibbles) 
  86.  
  87. + Menu Grob:     location of grob contained at #70551 
  88.                  size = 8 rows high by 136 bits wide 
  89.  
  90. Once you get to the grob in memory you must skip the 20 nibble prolog to get to 
  91. the pixel data.  The pixel data begins at the upper left corner of the display 
  92. and goes left to right, wrapping to the next row after 34 nibbles.  While the 
  93. nibbles go left to right as the address increases the bits in each nibble are 
  94. in right to left order. 
  95.  
  96. Example:         On Screen:          0101 
  97.                  In memory:          1010 = #A 
  98.  
  99. It is useful to have a data table which contains the address of the start of 
  100. each row of pixels.  This way you can take an arbitrary y coordinate and 
  101. transform it into an index to the data simply by multiplying y by 5.  Lets 
  102. look at this: 
  103.  
  104. Say y = 4, then  5 * y = 20, now the data table looks like this: 
  105.  
  106. start y=0   y=1   y=2   y=3   y=4 
  107.        |     |     |     |     | 
  108.        v     v     v     v     v 
  109.        04347|26347|48347|6A347|8C347.....  (stream of row addresses) 
  110.  
  111. So you use start+20 to get the row address.  Below I talk about building a 
  112. data 
  113. string. 
  114.  
  115. Here's my plug for using the stack display instead of PICT. 
  116.  
  117. 1)  Let PICT be the user's territory. 
  118. 2)  PICT sits and takes up 1098 bytes, unless you PURGE it. 
  119. 3)  The stack display is always the same size (131x64) 
  120.  
  121.  
  122. Making Data Space 
  123. ================= 
  124.  
  125. Quite often data tables are used in mcode programs.  If the data is going to be 
  126. generated by the program then it becomes a waste of space to attach non- 
  127. executing data to your program.  A routine at #05B7D will make a string object 
  128. whose data length (not including the header) is specified by the contents of 
  129. the c reqister.  The address is returned in the address register d0. 
  130.  
  131.               d0 
  132.                v 
  133.    C2A20|04000|123DF8734872394729834...   ...2312| 
  134.    <- header->|<--- length = c -----...   ...--->| 
  135.  
  136. All you need to do is: 
  137.  
  138.          move.p5  c, length      ;you specify length 
  139.          call     make_str       ;make_str = #05B7D 
  140.          swap.a   a, d0          ;d0 = string data area address 
  141.          move.w   a, r0          ;store the address somewhere for reference 
  142.  
  143.  
  144. Turning Off Interupts 
  145. ===================== 
  146.  
  147. Turning off interupts means turning off the keyboard, in a manner of speaking. 
  148. It means your program will only be interupted when you want input.  It is  
  149. simple to turn the interupts off, but you must be sure to turn them back on. 
  150.  
  151. Interupts Off:          clrb      15, st       ;clear bit 15 of status 
  152. register 
  153.                         intoff 
  154.  
  155. Interupts On:           inton 
  156.                         setb      15, st       ;set bit 15 of status register 
  157.  
  158. It would be nice if someone in-the-know would explain the flags the ST register 
  159. contains. 
  160.  
  161.  
  162. Keyboard input, the ML way 
  163. =========================== 
  164.  
  165. The instructions which must be used to grab key presses are OUT and IN. 
  166. Sounds simple enough, sure if you know how to do it.  Here's how it's done 
  167.  
  168. 1)  load register c with the row of keys you want to check (see table below) 
  169. 2)  perform  OUT.X  C to tell your HP to check that row 
  170. 3)  call IN_C = #01160, this address only contains:    IN.4   C  
  171.                                                        RET 
  172.     It seems that IN.4   C must be called, I think it messes with the  
  173.     return stack. 
  174. 4)  move the adress field of register c somewhere safe, say register a 
  175. 5)  clear register c 
  176. 6)  perform OUT.X  C to tell your HP to stop checking 
  177. 7)  now if you stored register c in register a in step (4) then the low 
  178.     nibbles of reg. a will contain bits set corresponding to the keys pressed 
  179.     in the row of interest. 
  180.  
  181. The Keyboard Map:  (from an article by Jan Brittenson) 
  182.  
  183.  
  184.              (IN) #20 #10 #08 #04 #02 #01 
  185.               --------------------------- 
  186.  
  187.         (OUT) |    6   5   4   3   2   1 
  188.  
  189.         #100  |        B   C   D   E   F 
  190.  
  191.         #080  |       PRG CST VAR  ^  NXT 
  192.  
  193.         #040  |       STO EVL  <   v   > 
  194.  
  195.         #020  |       COS TAN sqt pwr inv 
  196.  
  197.         #010  |   ON* ENT +/- EEX DEL <== 
  198.  
  199.         #008  |   alp SIN  7   8   9   / 
  200.  
  201.         #004  |   yel MTH  4   5   6   x 
  202.  
  203.         #002  |   blu  A   1   2   3   - 
  204.  
  205.         #001  |        '   0   .  SPC  + 
  206.  
  207.  
  208.    (*) The ON key is actually in a column of its own. 
  209.    #xxx refers to the keyboard scan bits. The column 
  210.    scan bit for the ON key is #8000. 
  211.  
  212. The numbers in the leftmost column are use to specify the row in the OUT  
  213. command and the numbers in the topmost row correspond to a positive result 
  214. from the IN command.  Note that these numbers have a binary representation  
  215. which has only one bit set.  So multiple bits set by the IN command mean  
  216. multiple key presses. 
  217.  
  218.  
  219. The Random Thing 
  220. ================ 
  221.  
  222. Your HP48sx maintains a hardware checksum at #00104 which is constantly 
  223. changing in a seemingly unpredictable manner.  You can get four random 
  224. nibbles at a time from the above address which may be masked down to the 
  225. range of numbers you are interested in. 
  226.  
  227. The program below takes two random numbers from the hardware crc, one 
  228. for the x coordinate and one for the y coordinate.  Two dummy instructions 
  229. were planted inbetween the two readings.  It turns out that without these 
  230. two dummy instructions, the static on the screen reduces to two predictable 
  231. lines. 
  232.  
  233.  
  234. Notice 
  235. ====== 
  236.  
  237. I claim no proficiency at ML programming, but maybe this info will help others 
  238. get started.  I did not hack out much of this.  Most of it came from studying 
  239. the source code for SCHIP v1.0 by Erik Bryntse.  For those not familiar with 
  240. this type of programming I suggest you actually run the program below and 
  241. recognize that only one pixel is being draw at a time...it's FAST!!!  By the 
  242. way, press the drop key to EXIT. 
  243.  
  244.  
  245.                                   The ML Freshie, 
  246.  
  247.                                   Zoom 
  248.                                   catto@ecn.purdue.edu 
  249.  
  250.  
  251. P.S.  Has anyone finished Ant?  You must see the final round, it's a hoot. 
  252.       The rolling (:() is actually quite easy, once you know how to get 
  253.       by it.  There's a lot more game after that. 
  254.  
  255. --------------------------begin STAR source------------------------------------ 
  256. ;FUZZ: makes random static on screen, drop key exits 
  257.  
  258. ;r0 = data string pointer 
  259. ;r1 = x coordinate in pixels 
  260. ;r2 = key data storage 
  261.  
  262. make_str        =       #05B7D 
  263. save_regs       =       #0679B 
  264. rest_regs       =       #067D2 
  265. crc_val         =       #00104 
  266. screen_ptr      =       #7055B 
  267. menu_ptr        =       #70551 
  268. in_c            =       #01160 
  269.  
  270. header 
  271. code 
  272.                 call            save_regs       ;save d0, d1, b, d 
  273.                 clr.w           c               ;c = 0 
  274.                 move.w          c, r2           ;initialize key storage 
  275.                 clr.w           a               ;a = 0 
  276.                 move.p3         #140, c         ;c = data string size (64*5+4) 
  277.                 call            make_str        ;make a data string 
  278.                 swap.a          a, d0           ;a = string address 
  279.                 move.w          a, r0           ;save string address in r0 
  280.                 move.a          a, d0           ;point to string 
  281.                 move.5          screen_ptr, d1  ;d1 = address of screen grob 
  282.                 move.p2         56, a           ;a = # rows in screen grob 
  283.                 call            fill_table      ;make data table 
  284.                 move.5          menu_ptr, d1    ;d1 = address of menu grob 
  285.                 move.p2         8, a            ;a = # rows in menu grob 
  286.                 call            fill_table      ;complete data table 
  287.                 clrb            15, st          ;interupt flag off 
  288.                 intoff                          ;turn off interupts 
  289.  
  290. main:           move.5          crc_val, d0     ;d0 = address of hardware crc 
  291.                 move.a          @d0, c          ;c = pseudo random # 
  292.                 clr.a           a               ;a = 0 
  293.                 move.p2         #7F, a          ;a = mask for screen width 
  294.                 and.a           a, c            ;c = random and x mask 
  295.                 move.w          c, r1           ;save x coordinate 
  296.  
  297.                 move.5          in_c, d0        ;these two lines do nothing 
  298.                 move.a          @d0, c          ;except make the crc random 
  299.                                                 ;it's a numbers game 
  300.  
  301.                 move.5          crc_val, d0     ;point to crc again 
  302.                 move.a          @d0, c          ;c = pseudo random # 
  303.                 move.p2         #3F, a          ;a = mask for screen height 
  304.                 and.a           a, c            ;c = random and y mask 
  305.                 move.a          c, a            ;a = c = y coordinate 
  306.                 add.a           c, c            ;c = 2*c 
  307.                 add.a           c, c            ;c = 4*c 
  308.                 add.a           a, c            ;c = 5*c 
  309.                 move.w          r0, a           ;get data string address 
  310.                 add.a           a, c            ;add offset for y coordinate 
  311.                 move.a          c, d0           ;point to row address 
  312.                 move.a          @d0, c          ;get row address 
  313.                 move.w          r1, a           ;get x coordinate in pixels 
  314.                 srb.w           a               ;a = x/2 (shift right bit) 
  315.                 srb.w           a               ;a = x/4 = x coordinate in nibs 
  316.                 add.a           c, a            ;a = row start + (x offset) 
  317.                 move.a          a, d0           ;d0 points to nib of interest 
  318.                 move.w          r1, c           ;c = x coordinate in pixels 
  319.                 clr.a           a               ;a = 0 
  320.                 move.p1         3, a            ;a = 3 (#11b) 
  321.                 and.a           c, a            ;get pixel position in nib 
  322.                 clr.a           c               ;c = 0 
  323.                 move.p1         1, c            ;set up c 
  324.  
  325. ;mirror_nib routine makes a nibble containing one bit set a x coordinate. 
  326. ;While grob nibbles are in order from left to right (up in memory), 
  327. ;the bits within the nibble are in reverse order.  So this routine 
  328. ;puts the nibble through a u-turn. 
  329.  
  330. mirror_nib:     dec.a           a               ;a = a - 1 
  331.                                                 ;if a(old) = 0 then sets carry 
  332.                 brcs            ready           ;jump if carry is set 
  333.                 add.a           c, c            ;c = 2*c = shift left bit c 
  334.                 jump            mirror_nib      ;loop 
  335.  
  336. ;Now the old nibble of the lcd grob is xor-ed with the new nibble 
  337. ;BTW a nibble is just a four bit chunk, a hex digit (ex. #1111b = #Fh = #15d) 
  338.  
  339. ready:          clr.a           a               ;xor old and new nibble 
  340.                 move.1          @d0, a          ;a = old nibble (OLD) 
  341.                 clr.w           d 
  342.                 move.a          c, d            ;d = new nibble (NEW) 
  343.                 move.a          a, c            ;a = c = OLD 
  344.                 and.a           d, c            ;c = OLD and NEW 
  345.                 swap.a          c, d            ;d = OLD and NEW 
  346.                 or.a            a, c            ;c = OLD or NEW 
  347.                 not.a           d               ;d = not(OLD and NEW) 
  348.                 and.a           d, c            ;c = OLD xor NEW 
  349.                 move.1          c, @d0          ;place xor nibble  
  350.  
  351.                 move.p3         #010, c         ;#010 specifies the row of 
  352.                 out.x           c               ;the drop key, the out.x 
  353.                                                 ;instruction scans a row 
  354.  
  355.                 call            in_c            ;in_c returns the results 
  356.                                                 ;you have to call this command 
  357.                                                 ;something to do with return 
  358.                                                 ;stack 
  359.  
  360.                 move.a          c, a            ;a = results 
  361.                 clr.a           c               ;c = 0 
  362.                 out.x           c               ;stop scanning 
  363.  
  364. ;the following checks if the drop was pressed AND released for program exit 
  365. ;that way your not pushing the drop key when program exits 
  366.  
  367.                 move.w          r2, c           ;get old key status 
  368.                 move.w          a, r2           ;put new key status 
  369.                 not.a           a               ;a = keys not pressed 
  370.                 and.a           c, a            ;and keys that were pressed 
  371.                 brbs            0, a, exit      ;bit 0 of contains flag 
  372.                 jump            main            ;for drop key column 
  373.  
  374. ;fill_table:  make a data table containing addresses of lcd rows 
  375. ;IN:    d1 points to grob data 
  376. ;       d0 points to data string 
  377. ;       a = # rows to set up 
  378. ;AFFECTS:       a, c, d0 
  379.  
  380. fill_table:     move.a          @d1, c          ;c = grob adress 
  381.                 add.a           16, c           ;add 20 to skip grob header 
  382.                 add.a           4, c 
  383.  
  384. ftlp:           move.a          c, @d0          ;put row address into table 
  385.                 add.a           16, c           ;add 34 to skip to next row 
  386.                 add.a           16, c           ;lcd grob width = 34 * 4 = 136 
  387.                 add.a           2, c 
  388.                 add.a           5, d0           ;skip to next address space 
  389.                 dec.b           a               ;decrement row counter 
  390.                 brnz.b          a, ftlp         ;continue if counter <> 0 
  391.                 ret 
  392.  
  393. exit:           inton                           ;interupts on (keyboard) 
  394.                 setb            15, st          ;flag interupts on 
  395.                 call            rest_regs       ;recall d, b, d1, d0 
  396.                 move.a          @d0, a          ;return to RPL operating system 
  397.                 add.a           5, d0 
  398.                 jump            @a 
  399.  
  400. endcode 
  401. -------------------------------end STAR source--------------------------------- 
  402.